package com.cn.qtms.filter;//类注释设置模板

import com.alibaba.fastjson.JSON;
import com.cn.qtms.common.constant.JwtSecurityConstants;
import com.cn.qtms.common.result.ErrorCode;
import com.cn.qtms.common.result.ResultUtil;
import com.cn.qtms.feign.Oauth2Client;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * @Name:GatewayTokenFilter
 * @Description:
 * @Author: zhangyang
 * @Date: 2019-11-12 22:17
 **/
@Component
public class GatewayTokenFilter extends ZuulFilter {
    private  static final String AUTH="auth";
    private static final Logger log = LoggerFactory.getLogger(GatewayTokenFilter.class);
    @Autowired
    private Oauth2Client oauth2Client;
    /**
     * 部分接口不需要token也能登陆
     */
    private static final String[] URLS=new String[]{"/sms/send","/aliyun/oss/upload"};
    /**
     * 部分接口对于ip请求时间有限制，10秒内只能请求一次
     */
    private static final String[] LIMIT_URLS=new String[]{"/sec-kill","/sec-goods"};
    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        String uri = request.getRequestURI();
        log.info("tokenFilter - 开始鉴权... uri="+uri);
        try {
            String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
            //不需要鉴权 直接访问
            for(String url:URLS){
                if(uri.indexOf(url)!=-1){
                    return null;
                }
            }
            //如果包含auth 说明url前往oauth2模块 不需要鉴权 oauth2会鉴权
            if(uri.indexOf(AUTH)==-1){
                if (StringUtils.isEmpty(authHeader)) {
                    requestContext.setSendZuulResponse(false);
                    requestContext.setResponseStatusCode(401);
                    String error = "authentication failed, reason: " + "Authorization is empty";
                    requestContext.setResponseBody(JSON.toJSONString(ResultUtil.error(ErrorCode.Unauthorized)));
                    requestContext.getResponse().setContentType("application/json;charset=UTF-8");
                    return null;
                }
                if (authHeader.startsWith(JwtSecurityConstants.BEARER_TOKEN_TYPE)) {

                    String token = authHeader.replaceFirst(JwtSecurityConstants.BEARER_TOKEN_TYPE, "").trim();
                    boolean limit=false;
                    for(String url:LIMIT_URLS){
                        if(uri.indexOf(url)!=-1){
                            limit=oauth2Client.checkLimited(token);
                            if(limit==false){
                                oauth2Client.limitedToken(token);
                            }
                        }
                    }
                    if(limit){
                        requestContext.setSendZuulResponse(false);
                        requestContext.setResponseStatusCode(400);
                        String error = "authentication failed, reason: " + "Authorization is empty";
                        requestContext.setResponseBody(JSON.toJSONString(ResultUtil.error(ErrorCode.METHOD_NOT_ALLOWED)));
                        requestContext.getResponse().setContentType("application/json;charset=UTF-8");
                        return null;
                    }
                    //判断接口是否需要限制ip
                    Boolean checkResult=true;
                    try{
                        //判断redis中token是否超时
                        final Map<String, Object> map = oauth2Client.checkToken(token);
                        if(map.size()>0) {
                            checkResult=false;
                        }
                    }catch (Exception ex){
                        checkResult=true;
                    }
                    if(!checkResult) {
                        // 传递给后续微服务
                        requestContext.addZuulRequestHeader(HttpHeaders.AUTHORIZATION, authHeader);
                    }else{
                        //不存在或者token过期
                        requestContext.setSendZuulResponse(false);
                        requestContext.setResponseStatusCode(555);
                        requestContext.setResponseBody(JSON.toJSONString(ResultUtil.error(ErrorCode.INVALIDTOKEN)));
                        Cookie cookie=new Cookie(JwtSecurityConstants.WEB_TOKEN," ");
                        cookie.setMaxAge(0);
                        requestContext.getResponse().setContentType("application/json;charset=UTF-8");
                    }
                }else{
                    requestContext.setSendZuulResponse(false);
                    requestContext.setResponseStatusCode(401);
                    String error = "authentication failed, reason: " + "Authorization is empty";
                    requestContext.setResponseBody(JSON.toJSONString(ResultUtil.error(ErrorCode.Unauthorized)));
                    requestContext.getResponse().setContentType("application/json;charset=UTF-8");
                }
            }
        }catch (Exception e){
            log.error("tokenFilter - [FAIL] EXCEPTION={}", e.getMessage(), e);
        }
        return null;
    }
}
